{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZUAAAEKCAYAAADaa8itAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAIABJREFUeJzt3Xt0lfWd7/H3FwJGruFWrtoAg0qLDGJQxJFSrdE6tSrK1KoFrSxth049MtPRTnuKLdVjl1ZbT2fkOFWB8b6UjJehLWpltNYLlzJYAeUi1QgqdwkmQOB7/thP4gZ2kp3kuezL57XWXtn79/yend+TwP7md/s+5u6IiIiEoUPSDRARkcKhoCIiIqFRUBERkdAoqIiISGgUVEREJDQKKiIiEhoFFRERCY2CioiIhEZBRUREQlOSdAPi1rdvXy8vL0+6GSIieWXZsmVb3b1fS/WKLqiUl5ezdOnSpJshIpJXzOwv2dTT8JeIiIRGQUVEREKjoCIiIqEpujmVTPbv3091dTV1dXVJN6UglZaWMmTIEDp16pR0U0QkYgoqQHV1Nd27d6e8vBwzS7o5BcXd2bZtG9XV1QwdOjTp5ohIxDT8BdTV1dGnTx8FlAiYGX369FEvsJAMGABmmR8DBiTdOkmYgkpAASU6+tkWmA8/bNsxKQqRBRUzu8/MPjKzP6eV3WZma8xspZlVmVlZ2rHvm9k6M3vLzM5JKz83KFtnZjemlQ81s9fMbK2ZPWpmnaO6FhERyU6UPZW5wLmHlT0LjHL30cDbwPcBzOxzwKXA54Nz/s3MOppZR+BfgS8DnwO+HtQF+Blwp7uPAHYAV0d4LUfo1q1bs+WbNm3ikksuAWDu3Ll85zvfia1tIiJJiSyouPuLwPbDyha5e33w8lVgSPD8AuARd9/r7u8A64BTgsc6d9/g7vuAR4ALLDWecibweHD+PODCdjU45HHiQYMG8fjjj7dcUUSkgCQ5p/JN4DfB88HAe2nHqoOypsr7ADvTAlRDeduFPE68ceNGRo0adUT5f/3Xf3HaaaexdetWtmzZwsUXX8y4ceMYN24cL7/88hH1zzjjDFasWNH4+vTTT2flypVs376dCy+8kNGjRzN+/HhWrlwJwE033cTtt9/eWH/UqFFs3Lix1e0XEWmLRIKKmf0AqAcebCjKUM3bUN7U97vGzJaa2dItW7a0trmhqaqq4tZbb2XhwoX07duX6667juuvv54lS5bwxBNPMH369CPOmT59OnPnzgXg7bffZu/evYwePZpZs2Zx0kknsXLlSm655RamTp0a89WIiBwp9n0qZjYN+Apwlrs3BIJq4Ji0akOATcHzTOVbgTIzKwl6K+n1j+Du9wD3AFRUVDQZfKL0wgsvsHTpUhYtWkSPHj0AeO6551i1alVjnY8//pjdu3fTvXv3xrIpU6Ywe/ZsbrvtNu677z6uvPJKAP7whz/wxBNPAHDmmWeybds2du3aFd8FSfHq37/p3nv//vG2RXJOrEHFzM4FbgC+4O6fpB16CnjIzO4ABgEjgNdJ9UhGmNlQ4H1Sk/mXubub2QvAJaTmWaYBT8Z3Ja03bNgwNmzYwNtvv01FRQUABw8e5JVXXuHoo49u8rwuXbpw9tln8+STT/LYY481Zlj+NB5/yswoKSnh4MGDjWXaHyKh++CDpFsgOSzKJcUPA68Ax5tZtZldDfwK6A48a2YrzGwOgLu/CTwGrAJ+C8xw9wNBL+Q7wO+A1cBjQV1IBaeZZraO1BzLvVFdSxg++9nPsmDBAqZOncqbb6YuobKykl/96leNddLnTtJNnz6d7373u4wbN47evXsDMHHiRB58MDV6uHjxYvr27UuPHj0oLy9n+fLlACxfvpx33nknyssSETlEZD0Vd/96huImP/jd/Wbg5gzlC4GFGco3kFodljeOP/54HnzwQaZMmcLTTz/NXXfdxYwZMxg9ejT19fVMnDiROXPmHHHeySefTI8ePbjqqqsay2666SauuuoqRo8eTZcuXZg3bx4AF198MfPnz2fMmDGMGzeO4447LrbrExGxTMMohayiosIPv0nX6tWrGfnFLzY/Tpxgl3/Tpk1MmjSJNWvW0KFDfiZBWL16NSNHjky6GYVvwICc/Xcs+c3Mlrl7RUv18vMTKgoffADumR8J/kecP38+p556KjfffHPeBhSJkVKoSMKUpTjHTZ06VcuFRSRv6E9fEREJjYKKiIiERkFFRERCo6AiIsVNNx0LlYJKmtr9tTz0xkPM/u/ZPPTGQ9TVN70bvanU9+kOT+7YGosXL25MybJ48WL++Mc/ZqyXnlZ/zpw5zJ8/H4BJkyZx+NJpKQLNpUlRCpXMtGIuVFr9FVjy/hIqH6ik/mA9e/btoWvnrsxYOINFVyxi3OBxibZt8eLFdOvWjQkTJjRb71vf+lZMLZKcpX0okjD1VIC6+joqH6hkZ91OavbV4Dg1+2rYWbeTygcqm+2xHO7mm2/m+OOP50tf+hJvvfVWY/mKFSsYP348o0eP5qKLLmLHjh1Aqkdxww03cMopp3Dcccfx0ksvAdC5c2d69uzJxo0bmTNnDnfeeSdjxoxpPJ5Jpp7RwYMHmTZtGj/84Q8BWLRoEaeddhpjx45lypQp1NTUHFJ//fr1jB07tvH12rVrOfnkkwF4/vnnOemkkzjxxBP55je/yd69ewEoLy9n69atACxdupRJkyZl/fMSkcKioAI89/5z1B+sz3is/mA9C1YvyOp9li1bxiOPPMKf/vQnFixYwJIlSxqPTZ06lZ/97GesXLmSE088kR//+Meffo/6el5//XV+8YtfNJZPmDCBX/7yl5SXl/Otb32L66+/nhUrVnDGGWdkfV319fVcfvnlHHfccfz0pz9l69at/PSnP+W5555j+fLlVFRUcMcddxxyzvDhw+nZs2djHrL777+fK6+8krq6Oq688koeffRR3njjDerr67n77ruzbouIFAcFFeC9mvfYs29PxmN79u1hw44NWb3PSy+9xEUXXUSXLl3o0aMHX/3qVwHYtWsXO3fu5Atf+AIA06ZN48UXX2w8b/LkyUAqx1eYN9S69tprGTVqFD/4wQ8AePXVV1m1ahWnn346Y8aMYd68efzlL3854rzp06dz//33c+DAAR599FEuu+wy3nrrLYYOHdqYS+zwaxARAQUVAI7pdgxdO3fNeKxr564M6zUs6/dK3em4dY466igAOnbsSH195h5TW0yYMIEXXnihMf29u3P22WezYsUKVqxYwapVq7j33iNzfF588cX85je/4ZlnnuHkk0+mT58+GVPtN0hPt69U+yLFTUEFOHvI2ZR0yLxmoaRDCZNHTs7qfSZOnEhVVRW1tbXs3r2bp59+GoCePXvSq1evxvmQ//iP/2jstWSje/fu7N69O+v6Da6++mrOO+88pkyZQn19PePHj+fll19m3bp1AHzyySe8/fbbR5xXWlrKOeecw7e//e3GzMgnnHACGzdubDw3/RrKy8tZtmwZQOONw0TyhlbMhUpBBTiq41EsumIRZaVldOvcDcPo1rkbZaVlLLpiEaUlpVm9z9ixY/na177GmDFjuPjiiw+Z/5g3bx7f+973GD16NCtWrOBHP/pR1u07//zzqaqqanGiPpOZM2cyduxYvvGNb9CnTx/mzp3L17/+9cZ7269ZsybjeZdffjlmRmVlJZAKNPfffz9TpkzhxBNPpEOHDo2rzWbNmsV1113HGWecQceOHVvVPpHE5Wgy2Xyl1Pd8mpa9dn8tVWuq2LBjA8N6DWPyyMlZB5RCc/vtt7Nr1y5mz54dyvsp9b1Ifss29b32qaQ5utPRXHbiZUk3I3EXXXQR69ev5/e//33STRGRPKOgIkeoqqpKugkikqc0pxIotmHAOOlnK1I8FFRITUJv27ZNH34RcHe2bdtGaWlxzk2JFBsNfwFDhgyhurqaLVu2JN2UglRaWsqQIUOSboaIxEBBBejUqRNDhw5NuhkiInlPw18iIhIa9VSk4DTsN1q/fT3Dew8v6v1GInFTUJGC0tR9cZ669Cne+/g9BRqRiGlHvRSM2v21DLpjEDvrdh5xzDC6dOrCJ/s/oWvnrpR0KMmJG7CJ5Itsd9RrTkUKRtWaqibvi+M4e/bvadcN2ESkZZEFFTO7z8w+MrM/p5X1NrNnzWxt8LVXUG5mdpeZrTOzlWY2Nu2caUH9tWY2La38ZDN7IzjnLmtLznkpKOu3r2/yvjiZtOYGbCKSnSh7KnOBcw8ruxF43t1HAM8HrwG+DIwIHtcAd0MqCAGzgFOBU4BZDYEoqHNN2nmHfy8pMsN7D2/yvjiZtOYGbCKSnciCiru/CGw/rPgCYF7wfB5wYVr5fE95FSgzs4HAOcCz7r7d3XcAzwLnBsd6uPsrnpoUmp/2XlKkJo+c3OR9cTJp7Q3YRKRlcc+p9Hf3zQDB188E5YOB99LqVQdlzZVXZyiXIlZaUprxvjhG5pHR1tyATUSykytLijP9r/c2lGd+c7NrSA2Vceyxx7alfZInxg0ex6aZmw65L86xPY7l/EfOP2SZccPqLy0rLiIDBsCHH2Y+1r+/bsgVkriDyodmNtDdNwdDWB8F5dXAMWn1hgCbgvJJh5UvDsqHZKifkbvfA9wDqSXF7bsEyXWZ7otzeKApiH0q+pBsnaZ+Vi0dk1aJO6g8BUwDbg2+PplW/h0ze4TUpPyuIPD8DrglbXK+Evi+u283s91mNh54DZgK/N84L0TyS0HegK2tH5IKRhKhyIKKmT1MqpfR18yqSa3iuhV4zMyuBt4FpgTVFwLnAeuAT4CrAILgMRtYEtT7ibs3TP5/m9QKs6OB3wQPEWmJ/mKXCGlHvUi+amlrVlP/t9t6Xr4r1usOiXbUi+SjAQNSH36ZHgMGJN06kRYpqIjkEg1NSZ5TUBGR4tC/f9uOSavkyj4VEWmt/v2bX8Ulh9KqtlgoqIjkq7Z+SCoYSYQUVESKjf5ilwhpTkVEREKjoCKSSzSZLHlOw18iuURDU5Ln1FMREZHQKKiIiEhoFFRERApVAml/FFRERApVAml/FFRERBoooWe7KaiIiDRQQs92U1AREZHQKKiIiEhoFFRERCQ0CioiIoUqgbQ/StMiIlKoEkj7o56KiEgDJfRsN/VUREQaKKFnu6mnIiIioVFQERGR0CioiIhIaBRURFpDuaFEmqWgItIayg0l0iwFFRERCU0iQcXMrjezN83sz2b2sJmVmtlQM3vNzNaa2aNm1jmoe1Twel1wvDztfb4flL9lZuckcS0iIvKp2IOKmQ0GvgtUuPsooCNwKfAz4E53HwHsAK4OTrka2OHufwXcGdTDzD4XnPd54Fzg38ysY5zXIiIih0pq+KsEONrMSoAuwGbgTODx4Pg84MLg+QXBa4LjZ5mZBeWPuPted38HWAecElP7RdpPk/5SgGIPKu7+PnA78C6pYLILWAbsdPf6oFo1MDh4Phh4Lzi3PqjfJ708wzmHMLNrzGypmS3dsmVLuBck0laa9JcClMTwVy9SvYyhwCCgK/DlDFW94ZQmjjVVfmSh+z3uXuHuFf369Wt9o0UaKDeUSLOSGP76EvCOu29x9/3AAmACUBYMhwEMATYFz6uBYwCC4z2B7enlGc4RicYHH4B75ofyRiVLw4k5IYmg8i4w3sy6BHMjZwGrgBeAS4I604Ang+dPBa8Jjv/e3T0ovzRYHTYUGAG8HtM1iEiu0XBiTkhiTuU1UhPuy4E3gjbcA9wAzDSzdaTmTO4NTrkX6BOUzwRuDN7nTeAxUgHpt8AMdz8Q46WISKFT76fVLPVHf/GoqKjwpUuXJt0MkdQHU3OK7P9mu0Xx89TvqJGZLXP3ipbqaUe9SFI06S8NCqhHpJt0iSRFE/vSoIDmg9RTERFpqzztTURJQUVECkOSw4l51puIkoa/RKQwaDgxJ2TVU1GiRhEpSlow0WrZDn+tM7PbgszAIiLFIT2DgmQl26AyGngb+LWZvRokaOwRYbtERIpHAS0vzyqouPtud/93d58A/DMwC9hsZvPM7K8ibaGISKEroJxyWc+pmNlXzawK+CXwc2AY8DSwMML2iYjkhgLqTUQp29Vfa0klfLzN3f+YVv64mU0Mv1kiIjkmz3oMSWkxqAQrv+a6+08yHXf374beKpGI1e6vpWpNFeu3r2d47+FMHjmZ0pLSpJslkvdaDCrufsDMvghkDCoi+WbJ+0uofKCS+oP17Nm3h66duzJj4QwWXbGIcYPHJd286A0Y0PRmvf79c/8v8nxvf4HLKkuxmd1M6uZYjwJ7GsrdfXl0TYuGshQXt9r9tQz8+UB27d11xLGy0jI2/+Pmwu+x5Hvm3Xxvf57KNktxtnMqE4Kv6b0VB85sbcNEknT7H2/PGFAA6g/Ws2D1Ai478bKYWyVSOLIKKu7+xagbIhK12v213PKHW5o8XrOvhg07NsTYIpHCk3XuLzP7W+DzQOPYQFOT9yK5qGpNVap/3YSjOh7FsF7D4muQSAHKdp/KHOBrwD8ABkwBPhthu0RCt377evYe2NvkcTNj8sjJMbZIpPBkm6ZlgrtPBXa4+4+B04BjomuWSPiG9x5O185dmzz+L3/zL4U/SS/RKaC7N7ZHtkGlNvj6iZkNAvYDQ6Npkkg0Jo+cTEmHzCO+ZaVlfO/078XcooTk+87wXG1/Ad29sT2yDSrPmFkZcBuwHNgIPBJVo0SiUFpSyqIrFlFWWka3zt0wjG6du1FWWsaiKxYVTy8l3/NM5Xv7C1xW+1QOOcHsKKDU3TOvy8xx2qciDbvpN+zYwLBew7SbXsJR4PtnQtmnYmZNzlqaGe6+oC2NE0nS0Z2O1l4Uid/hQadAd/+3tKT4/GaOOaCgIiLSFgU6z9JsUHH3q+JqiIiI5D9tfhQRCUP//gXb+2iNrIJKsPmxC/BF4NfAJcDrEbZLRFqg9P05JtP8SEuT9wUokc2PZlZmZo+b2RozW21mp5lZbzN71szWBl97BXXNzO4ys3VmttLMxqa9z7Sg/lozm9bW9ojkmyXvL2HQHYO49plrmbV4Ftc+cy0Dfz6QJe8vSbppUuSyDSp1wdeGzY/1tG/z4y+B37r7CcBfA6uBG4Hn3X0E8HzwGuDLwIjgcQ1wN4CZ9QZmAacCpwCzGgKRSCGr3V9L5QOV7KzbSc2+GhynZl8NO+t2UvlAJXX1dS2/iUhEsg0qTx+2+fEd4OG2fEMz6wFMBO4FcPd97r4TuACYF1SbB1wYPL8AmO8prwJlZjYQOAd41t23u/sO4Fng3La0SSSfVK2pov5gfcZjDen7JUfk6u7/CGU7Ub8GOODuT5jZ54CxwH+28XsOA7YA95vZXwPLgOuA/u6+GcDdN5vZZ4L6g4H30s6vDsqaKj+CmV1DqpfDscce28Zmi+SG9dvXs2ffnozH9uzbo/T9uaQA96G0JNueyv92991m9jfA2cBcgmGoNighFZTudveTSN1J8sZm6mea6fJmyo8sdL/H3SvcvaJfv36tba9IaGr31/LQGw8x+79n89AbD7VpqKq5xJhdO3dV+n5JVLY9lQPB178F5rj7k2Z2Uxu/ZzVQ7e6vBa8fJxVUPjSzgUEvZSDwUVr99EUBQ4BNQfmkw8oXt7FNzdIqGwnDkveXUPlAJfUH69mzbw9dO3dlxsIZLLpiEeMGj8v6fSaPnMyMhTMyHivpUKL0/ZKobHsq75vZ/wP+DlgY5P/K9txDuPsHwHtmdnxQdBawCngKaFjBNQ14Mnj+FDA1WAU2HtgVDJP9Dqg0s17BBH1lUBYqrbKRMIQ5uR5KYkylaZeIZNtT+TtSk+C3u/vOoCfRnjzh/wA8aGadgQ3AVaSC1GNmdjXwLqkbgQEsBM4D1gGfBHVx9+1mNhto+HT/ibtvb0ebjpD+QdCgZl8NAJUPVLL5HzerxyJZyWZyvTX5yMYNHsemmZvanhhTadolItneo/4T0vJ8BT2FzW39pu6+AsiU7fKsDHUdyNjXd/f7gPva2o6WhP1BIMUrisl1JcaUXJR1mpZipFU22dGcU8saJtcberrpNLkuhURBpRn6IGhZWJPPhU6T61Is2jTZXiyau/2sPgi0s7s1dNdJKRbqqTSj4YPg8L/ESzqU6IMAzTm1Vrsn10XygIJKC/RB0DTNOR0qm7mlnJlcby5Ne4GmD5F4KKhkIWc+CHKM5pw+lXdzS0WYPkTioTkVaTPNOaXEObcURpoXkSippyJtpjmnlLjmlvKuNyRFSUFF2kVzTvHMLSm7g+QLBRVpt2Kfc4pjbkkr7SRfaE5FpJ3imFvSSjvJFwoqIu0Ux8bG5u6h4jipFHm5TwsNCp/lyz/GsFRUVPjSpUuTboYUoIZ9KlHMLdXV1zHw9oHs3Lsz4/GeR/Xkg3/6IKfnVTItNGhY1KGFBrnPzJa5e6ZEwIdQT0UkJA1zSz+c+EMuO/GyUD/gS0tKmXnazCaPH/ADOX1veqX0KR6aqJfYKavxocL4eeT6vIoWGhQPBRWJlfZaHKo1P4/hvYfTrXO3vMxgoIUGxUPDXxIbDYEcqrU/j3zOYNDcQoNcD4jSOgoqEptshkCKSdWaKvbW7814bG/93iN+HvmcPj+fA6K0joa/JDYaAjnUmi1rqK2vzXistr6Wt7a+dUR5vmYwUEqf4qGgIrFRVuNDbavb1uzxrbVbM5bnawaDfA2I0joKKhIb3VL3UH2P7tvs8X5d+sXUkvjka0CU7GlORWLT1jmBQt2FfXzf4+lS0iXjsS6dunBcn+NibpFI+2lHvcSuNTvPC3kXdl19HQN/PvCQzMMNykrLlHlYckq2O+oVVCRn1e6vZdAdgwr6Qzdfg6Y2sBafbIOK5lQkZxXDLux8nLzWBlZpjoKK5KxiWYKcT5PXulmYtEQT9ZKztAs792gDq7QksaBiZh3N7E9m9kzweqiZvWZma83sUTPrHJQfFbxeFxwvT3uP7wflb5nZOclciURFu7Cj19qVdcXSe5S2S7Knch2wOu31z4A73X0EsAO4Oii/Gtjh7n8F3BnUw8w+B1wKfB44F/g3M+sYU9slBvmcliQfLHl/CYPuGMS1z1zLrMWzuPaZaxn484EseX9Jk+eo9ygtSWT1l5kNAeYBNwMzgfOBLcAAd683s9OAm9z9HDP7XfD8FTMrAT4A+gE3Arj7/wnes7Fec99bq7/yT5Q3vypWbV1ZF8cyaK0sy025vvrrF8A/A92D132Ane7eMFhbDQwOng8G3gMIAs6uoP5g4NW090w/RwpIPk1k54u2rqyLOoeXVpblv9iDipl9BfjI3ZeZ2aSG4gxVvYVjzZ1z+Pe8BrgG4Nhjj21Ve0UKUXvmRqJaBq2VZYUhiZ7K6cBXzew8oBToQarnUmZmJUFvZQiwKahfDRwDVAfDXz2B7WnlDdLPOYS73wPcA6nhr9CvSCTPtDe5ZxS9x2LYl1QMYp+od/fvu/sQdy8nNdH+e3e/HHgBuCSoNg14Mnj+VPCa4PjvPTUR9BRwabA6bCgwAng9pssQyWu5uLJOK8sKQy7tU7kBmGlm60jNmdwblN8L9AnKZ/LpBP2bwGPAKuC3wAx3PxB7q0XyUC6urNPKssKg3F8iMcjVFU25tLJOCTZzmxJKNkFBReKWr0kjk6CfVe5SUGmCgorEqRgyLYctl3pP8qlc36ciUhS0oqn1tC8pvymoiESo2Fc05epckkRHQUUkQu3dD5LPtDu+OOXSkmKRgpOL+0HikL47vmZfDY5Ts6+GnXU7qXygssVsyJK/FFREIpSL+0HiEMd9V1qbtl/ioeEvkYjl4y2D2yvquSQNreUuBRWRGBTbiqYo55KUeDK3afhLREIX5VySbmmc29RTkZyh5aeFI8r7rhT7Mu1cp6AiOUFj5IUnqrmkYl6mnQ+UpkUSp1Qm0hpKPJmMbNO0aE5FElcMY+Ra/hqeYl2mnS80/CWJK/Qxcg3tha8Yl2nnCwUVSVwhj5Fr+Wt0im2Zdr7Q8JckrpBTmRTD0J5IOvVUQqClsO0T5fLTpBX60J7I4RRU2knj5eEo1DHyQh7aE8lES4rbQUthpSVa/iqFQkuKY6DxcmmJlr9KsdHwVztovFyyUahDeyKZKKi0g8bLJVta/irFQsNf7VDIS2FFRNpCQaUdNF4uInIoDX+1k8bLRUQ+paASAo2Xi4ikxD78ZWbHmNkLZrbazN40s+uC8t5m9qyZrQ2+9grKzczuMrN1ZrbSzMamvde0oP5aM5sW97WIiMihkuip1AP/6O7Lzaw7sMzMngWuBJ5391vN7EbgRuAG4MvAiOBxKnA3cKqZ9QZmARWAB+/zlLvviP2KRPKMUgtJVGIPKu6+GdgcPN9tZquBwcAFwKSg2jxgMamgcgEw31Nb/181szIzGxjUfdbdtwMEgelc4OHYLkYkDym1kEQp0dVfZlYOnAS8BvQPAk5D4PlMUG0w8F7aadVBWVPlItKE9FT8NftqcJyafTXsrNtJ5QOVunmYtFtiQcXMugFPAP/L3T9urmqGMm+mPNP3usbMlprZ0i1btrS+sSIxi+pOkUotJFFLZPWXmXUiFVAedPeGf8UfmtlAd98cDG99FJRXA8eknT4E2BSUTzqsfHGm7+fu9wD3QCqhZEiXIRKJKIenlFpIopbE6i8D7gVWu/sdaYeeAhpWcE0DnkwrnxqsAhsP7AqGx34HVJpZr2ClWGVQJpK3oh6eakgtlIlSC0kYkhj+Oh34BnCmma0IHucBtwJnm9la4OzgNcBCYAOwDvh34O8Bggn62cCS4PGThkl7kXwV9fCUUgtJ1JJY/fUHMs+HAJyVob4DM5p4r/uA+8JrnUiyoh6eKuS7bOayYlrCrR31IjkkjszXSi0Ur2Jbwq07P4rkEN0psrAU0t1hdedHkRBEtbS3Kcp8XViKcQm3hr9EmpDUsIWGpwpHMS7hVlARySB9aW+DhnmOygcqIx+2UObrwlCMd4fV8JdIBsUwbBH30F4xKsYl3OqpiGRQ6MMWxbYiKSnFuIRbQUUkg0Ietkh6aK/YFNscmYKKSAaTR05mxsKMe27zftgim6E9zeeEq5jmyDSnIpJBIS/tLfShPUmWeioiTSjUYYtCHtqT5GlHvUiR0a59aQvtqBeRjArDLPwuAAAEUklEQVR5aE+Sp+EvkSJUqEN7kjwFFZEiVUwrkiQ+Gv4SEZHQKKiIiEhoFFRERCQ0CioiIhKaotunYmZbgL8k3Y5m9AW2Jt2IBBTjdRfjNYOuO1991t37tVSp6IJKrjOzpdlsMCo0xXjdxXjNoOtOuh1R0/CXiIiERkFFRERCo6CSe+5JugEJKcbrLsZrBl13QdOcioiIhEY9FRERCY2CSgLM7D4z+8jM/tzE8UlmtsvMVgSPH8Xdxii0dN1BnUnBNb9pZv8dZ/uikMXv+ntpv+c/m9kBM+sddzvDlsV19zSzp83sf4Lf9VVxtzEKWVx3LzOrMrOVZva6mY2Ku41R0/BXAsxsIlADzHf3I/5Rmdkk4J/c/Stxty1KWVx3GfBH4Fx3f9fMPuPuH8XdzjC1dM2H1T0fuN7dz4ylcRHK4nf9L0BPd7/BzPoBbwED3H1fzE0NVRbXfRtQ4+4/NrMTgH9197PibmeU1FNJgLu/CGxPuh1xy+K6LwMWuPu7Qf28DijQ6t/114GHI2xObLK4bge6m5kB3YK69XG0LUpZXPfngOeDumuAcjPrH0fb4qKgkrtOC4YGfmNmn0+6MTE5DuhlZovNbJmZTU26QXExsy7AucATSbclJr8CRgKbgDeA69z9YLJNisX/AJMBzOwU4LPAkERbFDLdTyU3LSeVEqHGzM4D/hMYkXCb4lACnAycBRwNvGJmr7r728k2KxbnAy+7e7H0YM8BVgBnAsOBZ83sJXf/ONlmRe5W4JdmtoJUMP0TBdBDS6eeSg5y94/dvSZ4vhDoZGZ9E25WHKqB37r7HnffCrwI/HXCbYrLpRTI0FeWriI11Onuvg54Bzgh4TZFLvi/fZW7jwGmAv1IXXvBUFDJQWY2IBhrbugidwC2JduqWDwJnGFmJcFw0KnA6oTbFDkz6wl8gdT1F4t3SfVICeYUjgc2JNqiGJhZmZl1Dl5OB14stN6Zhr8SYGYPA5OAvmZWDcwCOgG4+xzgEuDbZlYP1AKXegEs02vput19tZn9FlgJHAR+7e5NLj/OB1n8rgEuAha5+55EGhmBLK57NjDXzN4ADLgh6J3mtSyueyQw38wOAKuAqxNqamS0pFhEREKj4S8REQmNgoqIiIRGQUVEREKjoCIiIqFRUBERkdAoqIjEJNij8PdZ1KsJvpY3l9FZJBcpqIjEpwxoMaiI5DNtfhSJz63A8CDv0wvAaKAXqc1xP3T3YtpRLwVKQUUkPjcCo9x9jJmVAF3c/eMgr9urZvZUIWROkOKmoCKSDANuCW7qdBAYDPQHPki0VSLtpKAikozLSWWoPdnd95vZRqA02SaJtJ8m6kXisxvoHjzvCXwUBJQvkrpZk0jeU09FJCbuvs3MXg6WCS8BTjCzpaRuVrUm2daJhENZikVEJDQa/hIRkdAoqIiISGgUVEREJDQKKiIiEhoFFRERCY2CioiIhEZBRUREQqOgIiIiofn/zYHZIaME1DgAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cost theta: [[0.48518509]]\n",
      "Train Accuracy: 0.88\n",
      "finished!\n"
     ]
    }
   ],
   "source": [
    "# -*- coding: UTF-8 -*-\n",
    " #numpy库的使用，请参考：https://www.jianshu.com/p/a260a8c43e44\n",
    " #matplotlib库请参考：https://matplotlib.org/api/index.html\n",
    "\n",
    "import xlrd     # 导入必备的 xlrd 库，目的是为了调用 xlrd.open_workbook 函数打开 excel 文件，读取数据\n",
    "import matplotlib.pyplot as plt     # 导入必备的 matplotlib 库，并且将其中的 matplotlib.pyplot 重名为 plt, 目的是为了后续的绘图需要，也是为了编程方便，简写为 plt\n",
    "import numpy as np      # 导入必备的 numpy 库，并且将其重名为 np, 目的是为了后续的矩阵的定义、运算、操作等，也是为了编程方便，简写为 np\n",
    "\n",
    "# 定义函数loadData函数，输入参数是 filename 指代文件名，返回数据data，目的是从.xls文件中加载数据，并存储为numpy中的array格式\n",
    "def loadData(filename):\n",
    "    workbook = xlrd.open_workbook(filename)         # 通过调用 xlrd.open_workbook 函数打开 excel 文件，读取数据，并返回给 workbook 变量\n",
    "    boyinfo = workbook.sheet_by_index(0)            # 通过使用属性 sheet_by_index 得到  excel 文件 中的工作簿，其中 sheet_by_index(0) 表示是第一个工作簿，在 python 中，下标从 0 开始\n",
    "    col_num = boyinfo.ncols                         # 通过使用属性 ncols 得到 excel 文件 中第一个工作簿的 列数，并赋值给 col_num\n",
    "    row_num = boyinfo.nrows                         # 通过使用属性 nrows 得到 excel 文件 中第一个工作簿的 行数，并赋值给 row_num\n",
    "    col0 = boyinfo.col_values(0)[1:]                # 通过使用属性 col_values(0)[1:] 得到 excel 文件 中第一列数据中，从第2行到最后一行的所有数据，并赋值给 col0\n",
    "    data = np.array(col0)                           # 通过使用 np.array 函数， 将 col0 转换成数组，并赋值给 data\n",
    "    if col_num == 1:                                # 条件判断语句： 如果列数 col_num 为1， 只有一列，那么直接返回数据 data\n",
    "        return data                                     # 返回data\n",
    "    else:                                           # 否则，如果不止一列数据，需要遍历所有列的数据\n",
    "        for i in range(col_num-1):                      # 通过使用for循环达到遍历的目的\n",
    "            coltemp = boyinfo.col_values(i+1)[1:]           # 从第二行开始，表头不算，遍历从 第二列 开始到最后一列的数据\n",
    "            data = np.c_[data, coltemp]                     # 通过使用 np.c_ 函数将 第一列的数据 和后面 所有列的数据组合起来，并赋值给 data\n",
    "    return data                                     # 返回data\n",
    "\n",
    "# 定义一个 plotData 函数，输入参数是 数据 X 和标志 flag: y，返回作图操作 plt, p1, p2 ， 目的是为了画图\n",
    "def plotData(X, y):\n",
    "    pos = np.where(y==1)                            # 通过使用 np.where 函数查找所有满足条件的数据，查找所有满足标志 y == 1 的数据，并赋值给 pos\n",
    "    neg = np.where(y==0)                            # 通过使用 np.where 函数查找所有满足条件的数据，查找所有满足标志 y == 0 的数据，并赋值给 neg\n",
    "    # 通过使用 plt.plot 函数作图，对所有满足标志 y == 1 的数据作图，点采用 s (正方形)，代表 square, 点的大小为 7 单位，颜色为 红色 red\n",
    "    p1 = plt.plot(X[pos, 0], X[pos, 1], marker='s', markersize=7, color='red')[0]\n",
    "    # 请补全 通过使用 plt.plot 函数作图，对所有满足标志 y == 0 的数据作图，点采用 o (圆形)，代表 circle, 点的大小为 7 单位，颜色为 绿色 green \n",
    "    p2 = plt.plot(X[neg, 0], X[neg, 1], marker='o', markersize=7, color='green')[0]\n",
    "\n",
    "    return p1, p2                                   # 返回作图操作plt, p1, p2\n",
    "\n",
    "# normalization： 定义一个 normalization 函数，输入参数是原始数据 X ，返回归一化后的数据 X_norm ， 目的是为了数据预处理，得到归一化后的数据 X_norm\n",
    "def normalization(X):\n",
    "    Xmin = np.min(X,axis=0)                                        # 请补全 通过使用 np.min 函数，计算原始数据沿着 axis=0 方向的最小值，即：求每一列的最小值，并赋值给 Xmin\n",
    "    Xmax = np.max(X,axis=0)                                 # 请补全 通过使用 np.max 函数，计算原始数据沿着 axis=0 方向的最大值，即：求每一列的最大值，并赋值给 Xmax\n",
    "    Xmu  = np.mean(X,axis=0)                               # 请补全 通过使用 np.mean 函数，计算原始数据均值，并赋值给 Xmu                 \n",
    "    X_norm =  (X-Xmu)/(Xmax-Xmin)                          # 请补全 计算归一化后的数据，归一化公式为：(X-Xmu)/(Xmax-Xmin)，归一化后数据范围为 [-1,1]\n",
    "    return X_norm  # 返回数据预处理，归一化后的数据 X_norm\n",
    "\n",
    "# plot decision boundary：定义一个 plotDecisionBoundaryn 函数，输入参数是 训练集 trainX, 训练集 trainY, 直线斜率截距相关参数 w, 迭代次数 iter_num ，目的是为了画出决策的判断边界\n",
    "def plotDecisionBoundary(trainX, trainY, w, iter_num = 0):\n",
    "    # prepare data\n",
    "    xcord1 = [];ycord1 = [];xcord2 = [];ycord2 = [] # 准备数据，定义四个空的列表，并分别赋值给 xcord1、ycord1、xcord2、ycord2，进行初始化\n",
    "    m, n = np.shape(trainX)                         # 通过使用 np.shape 函数，得到训练集 trainX 的形状大小，其中，m 为训练集 trainX 的行数，n 为训练集 trainX 的列数\n",
    "    for i in range(m):                              # 通过使用 for 循环语句，遍历训练集 trainX 所有的行，其中，i 可以取得值分别是 0，1，2，...，m-1，总共是 m 行\n",
    "        if trainY[i] == 1:                          # 通过使用 if 条件判断语句，如果训练集 trainY（标志）中的元素为 1，那么将训练集 trainX中的 trainX[i,1] 和 trainX[i,2] 分别添加到 xcord1 和 ycord1 列表中\n",
    "            xcord1.append(trainX[i,1])              # 通过 append 的方法，将训练集 trainX中 的 trainX[i,1] 添加到 xcord1 列表中，保存的是 pos 的横坐标, 代表 positive 的数据\n",
    "            ycord1.append(trainX[i,2])              # 通过 append 的方法，将训练集 trainX中 的 trainX[i,2] 添加到 ycord1 列表中，保存的是 pos 的纵坐标, 代表 positive 的数据\n",
    "        else:                                       # 否则，如果训练集 trainY（标志）中的元素不为 1，那么将训练集 trainX中的 trainX[i,1] 和 trainX[i,2] 分别添加到 xcord2 和 ycord2 列表中     \n",
    "            xcord2.append(trainX[i,1])              # 通过 append 的方法，将训练集 trainX中 的 trainX[i,1] 添加到 xcord2 列表中，保存的是 neg 的横坐标, 代表 negative 的数据\n",
    "            ycord2.append(trainX[i,2])              # 通过 append 的方法，将训练集 trainX中 的 trainX[i,2] 添加到 ycord2 列表中，保存的是 neg 的纵坐标, 代表 negative 的数据   \n",
    "    x_min = min(trainX[:,1])                        # 通过使用 min 函数，计算出 trainX[:,1] ，即 trainX 第2列的最小值，并赋值给 x_min   \n",
    "    y_min = min(trainX[:,2])                        # 通过使用 min 函数，计算出 trainX[:,2] ，即 trainX 第3列的最小值，并赋值给 y_min  \n",
    "    x_max = max(trainX[:,1])                        # 通过使用 max 函数，计算出 trainX[:,1] ，即 trainX 第2列的最大值，并赋值给 x_max  \n",
    "    y_max = max(trainX[:,2])                        # 通过使用 max 函数，计算出 trainX[:,2] ，即 trainX 第3列的最大值，并赋值给 y_max \n",
    "\n",
    "    # plot scatter  & legend\n",
    "    fig = plt.figure(1)                              # 通过使用 plt.figure 函数，开始创建一个图形窗口，并赋值给 fig\n",
    "    # 通过使用 plt.scatter 函数，绘制散点图，横坐标为 xcord1, 纵坐标为 ycord1，标记大小为30，颜色为红色，形状样式为 s (正方形)，代表 square, 图例标签为 'I like you'\n",
    "    plt.scatter(xcord1, ycord1, s=30, c='red', marker='s', label='I like you')\n",
    "    # 请补全 通过使用 plt.scatter 函数，绘制散点图，横坐标为 xcord2, 纵坐标为 ycord2，标记大小为30，颜色为绿色，形状样式为 o (圆形)，代表 circle, 图例标签为 'I don't like you'\n",
    "    plt.scatter(xcord2,ycord2,s=30,c='green',marker='o',label=\"I don't like you\")\n",
    "    \n",
    "    plt.legend(loc='upper right')                   # 设置图例的位置为右上角\n",
    "\n",
    "    # set axis and ticks\n",
    "    delta_x = x_max-x_min                           # 计算横坐标的极差为横坐标最大值与最小值的差，并赋值给 delta_x\n",
    "    delta_y = y_max-y_min                           # 计算纵坐标的极差为纵坐标最大值与最小值的差，并赋值给 delta_y\n",
    "    # 设置横坐标的刻度：从 x_min - delta_x / 10 到 x_max + delta_x / 10，使用 np.arange 函数创建数组，步长为 1，并赋值给 my_x_ticks\n",
    "    my_x_ticks = np.arange(x_min - delta_x / 10, x_max + delta_x / 10, 1)\n",
    "    # 设置纵坐标的刻度：从 y_min - delta_y / 10 到 y_max + delta_y / 10，使用 np.arange 函数创建数组，步长为 1，并赋值给 my_y_ticks\n",
    "    my_y_ticks = np.arange(y_min - delta_y / 10, y_max + delta_y / 10, 1)\n",
    "\n",
    "    plt.xticks(my_x_ticks)                          # 通过使用 plt.xticks 函数，设置作图的横坐标的刻度为 my_x_ticks\n",
    "    plt.yticks(my_y_ticks)                          # 通过使用 plt.yticks 函数，设置作图的纵坐标的刻度为 my_y_ticks\n",
    "    # 通过使用 plt.axis 函数，设置作图的横坐标和纵坐标的显示范围，分别是[x_min-delta_x/10, x_max+delta_x/10] 和 [y_min-delta_y/10, y_max+delta_y/10]    \n",
    "    plt.axis([x_min-delta_x/10, x_max+delta_x/10, y_min-delta_y/10, y_max+delta_y/10])\n",
    "\n",
    "    # drwa a line：绘制一条直线，用于决策判断\n",
    "    x = np.arange(x_min-delta_x/10, x_max+delta_x/10, 0.01) # 通过使用 np.arange 函数创建数组， 从 x_min - delta_x / 10 到 x_max + delta_x / 10，步长为 0.01，并赋值给 x\n",
    "    y = (-w[0]-w[1]*x)/w[2]                              # 通过公式计算得到直线的纵坐标： y = (-w[0]-w[1]*x)/w[2]\n",
    "    plt.plot(x, y.T)                                # 通过使用 plt.plot 函数绘制图象，其中，横坐标是 x , 纵坐标是 y.T， “.T” 表示的是矩阵的转置，因为绘图时需要横纵坐标的维度一致\n",
    "\n",
    "    # figure name：设置图像的文件名和标题名\n",
    "    # 设置图像的文件名为 'Training ' + str(iter_num) + ' times.png'，其中，str(iter_num) 表示将迭代次数 iter_num 转变成字符串，图片格式为 “png”\n",
    "    fig_name = 'Training ' + str(iter_num) + ' times.png'   \n",
    "    # 设置图像的标题名为'Training ' + str(iter_num) + ' times.png'，其中，str(iter_num) 表示将迭代次数 iter_num 转变成字符串，图片格式为 “png”\n",
    "    plt.title(fig_name)\n",
    "    fig.savefig(fig_name)                           # 通过使用 fig.savefig 函数，保存图片，分辨率等参数采取默认值\n",
    "    plt.show(fig)                                      # 通过使用 plt.show 函数，显示绘制好的图片，注意的是必须关闭图像窗口，才可以进入执行后续的程序\n",
    "\n",
    "# sigmoid: 定义一个 激活（激励）函数 sigmoid 函数 （activation function），输入参数是 wx， 返回的是 sigmoid 函数值\n",
    "def sigmoid(wx):\n",
    "    sigmoidV = 1.0/(1.0+np.exp(-wx))                   # 请补全  计算激活函数 sigmoid 函数 的函数值，计算公式为：1.0/(1.0+np.exp(-wx))\n",
    "    return sigmoidV                    \n",
    "\n",
    "# loss fuc Y_ 预测值 Y 真值\n",
    "def loss(X, Y, w):                                  # 定义一个 损失函数 loss 函数 （loss function），输入参数是 X, Y, w， 返回的是 损失函数的值\n",
    "    m, n = np.shape(X)                              # 通过使用 np.shape 函数，得到数据集 X 的形状大小，其中，m 为数据集 X 的行数，n 为数据集 X 的列数\n",
    "    trainMat = np.mat(X)                            # 通过使用 np.mat 函数，将数据集 X 转变成矩阵类型，并赋值给 trainMat\n",
    "    Y_ = []                                         # 准备数据，定义一个空的列表，并赋值给 Y_，进行初始化, 后续会通过 append 的方法向空列表内不断添加新的元素\n",
    "    for i in np.arange(m):                          # 通过 for 循环结构，遍历数据集 X 所有的行，其中，i 可取的数依次为：0，1 ，2，....，m-1， 数据集 X总共有 m 行\n",
    "        # 通过 append 的方法向空列表 Y_ 内不断添加新的元素，新元素是通过 训练的矩阵数据集  trainMat[i] 乘以权重 w 之后，再计算激活函数 sigmoid 的函数值\t\n",
    "        Y_.append(sigmoid(trainMat[i]*w))\n",
    "    m = np.shape(Y_)[0]                             # 通过使用 np.shape 函数，得到数据集 X 的形状大小，其中，np.shape(Y_)[0] 为数据集 X 的行数，并赋值给 m        \n",
    "    sum_err = 0.0                                   # 初始化误差的总和为 0.0, 赋值给 sum_err， 后续会不断更新 误差的总和 sum_err 的数值   \n",
    "    for i in range(m):                              # 通过 for 循环结构，遍历数据集 Y_ 所有的行，其中，i 可取的数依次为：0，1 ，2，....，m-1， 数据集 Y_ 总共有 m 行    \n",
    "        # 请补全 更新误差的总和 sum_err 的数值， 每次 误差的总和 sum_err 递减 Y[i]*np.log(Y_[i])+(1-Y[i])*np.log(1-Y_[i])，这是 交叉熵损失函数（ Cross Entropy Loss ）的计算公式    \t\n",
    "        sum_err -= Y[i]*np.log(Y_[i])+(1-Y[i])*np.log(1-Y_[i])\n",
    "    return sum_err/m                                # 返回 sum_err\n",
    "\n",
    "# BGD 批量梯度下降法求最优参数\n",
    "# 定义一个BGD 函数，即：批量梯度下降法（Batch Gradient Descent，BGD），输入参数是 数据集 X 和 y, \n",
    "# 迭代次数 iter_num, 学习率 alpha，又写作 lr (learning rate), 它表示每次向着J最陡峭的方向迈步的大小， 返回的是 权重 w\n",
    "# 通过批量梯度下降法（Batch Gradient Descent，BGD），不断更新权重 W\n",
    "def BGD(X, y, iter_num, alpha):\n",
    "    trainMat = np.mat(X)                            # 通过使用 np.mat 函数，将数据集 X 转换成矩阵类型，并赋值给 trainMat\n",
    "    trainY = np.mat(y).T                            # 通过使用 np.mat 函数，将数据集 y 转换成矩阵类型，并且转置，然后赋值给 trainY \n",
    "    m, n = np.shape(X)                              # 通过使用 np.shape 函数，得到数据集 X 的形状大小，其中，m 为数据集 X 的行数，n 为数据集 X 的列数    \n",
    "    w = np.ones((n,1))                              # 通过使用 np.ones 函数，创建元素全为 1 的矩阵，矩阵的大小为 n 行 1 列，并赋值给 w, 即：进行权重 w 的初始化，令其全为 1  \n",
    "    for i in range(iter_num):                       # 通过 for 循环结构，开始进行迭代，其中，i 可取的数依次为：0，1 ，2，....，iter_num-1， 迭代次数总共有 iter_num 次\n",
    "        error = sigmoid(trainMat*w)-trainY # 计算迭代的误差 error：将预测得到的激活函数的数值 sigmoid(trainMat*w) 减去 实际的 trainY 数值\n",
    "        w =  w - (1.0/m)*alpha*trainMat.T*error      #请补全                           # 更新权重 w , BGD 批量梯度下降法 的核心， w = w - (1.0/m)*alpha*trainMat.T*error\n",
    "    return w                                        # 返回 w\n",
    "\n",
    "# classify：定义一个 classify 函数，输入参数是 wx， 返回的是标志 1 或者 0\n",
    "def classify(wx):\n",
    "    prob = sigmoid(wx)                              # 计算概率：将激活函数 sigmoid(wx) 的数值作为预测的概率，并赋值给 prob\n",
    "    if prob > 0.5:                                  # 如果 概率 prob 大于 0.5， 那么返回数值 1  \n",
    "        return 1\n",
    "    else:                                           # 否则，如果 概率 prob 不大于 0.5， 那么返回数值 0\n",
    "        return 0\n",
    "\n",
    "# predict：定义一个 predict 函数，输入参数是 测试集 testX 和权重 w， 返回的是预测的结果 result\n",
    "def predict(testX, w):\n",
    "    m, n = np.shape(testX)                          # 通过使用 np.shape 函数，得到测试集 testX 的形状大小，其中，m 为测试集 testX 的行数，n 为测试集 testX 的列数  \n",
    "    testMat = np.mat(testX)                         # 通过使用 np.mat 函数，将测试集 testX 转换成矩阵类型，并赋值给 testMat\n",
    "    result = []                                     # 准备数据，定义一个空的列表，并赋值给结果 result，进行初始化, 后续会通过 append 的方法向空列表内不断添加新的元素\n",
    "    for i in np.arange(m):                          # 通过 for 循环结构，遍历测试集 testX 所有的行，其中，i 可取的数依次为：0，1 ，2，....，m-1， 测试集 testX 总共有 m 行\n",
    "        # 通过 append 的方法向空列表 result 内不断添加新的元素，新元素是通过调用 classify 函数进行预测得到，将返回的浮点型的 1 或者 0 添加到 空列表 result 内\n",
    "        result.append(classify(float(testMat[i]*w)))\n",
    "    return result                                   # 返回预测结果result\n",
    "\n",
    "# Precision：定义一个 Precision 函数，输入参数是数据集 X, Y 和权重 w， 返回的是 测试集的正确率 \n",
    "def Precision(X, Y, w):\n",
    "    result = predict(X, w)                          # 通过调用 predict 函数，输入测试集 X 和权重 w， 计算得到预测结果，并把返回的结果赋值给 result \n",
    "    right_sum = 0                                   # 进行初始化预测正确的数目，赋值 0 给 right_sum，后续如果预测正确，会不断增加 1 \n",
    "    # 通过 for 循环结构，开始进行遍历，其中，i 可取的数依次为：0，1 ，2，....，len(result)-1， 预测结果 result 内元素的个数总和为 len(result) \n",
    "    for i in range(len(result)):\n",
    "        if result[i]-int(Y[i]) == 0:                # 通过条件判断语句 if, 如果结果 result 的元素与 int(Y[i])相等，即：预测正确！ 那么更新预测正确的数目 right_sum\n",
    "            right_sum += 1                          # 如果预测正确！ 那么更新预测正确的数目 right_sum，每次递增加 1\n",
    "    # 最后返回测试集预测的正确率，计算公式为：1.0*right_sum/len(Y)，注意：乘以 1.0 的原因是把正确率变成浮点型，当然也可以直接用 float 强制转换\n",
    "    return 1.0*right_sum/len(Y)                     \n",
    "\n",
    "# python 主程序，当本文件被执行的时候，运行下列语句：\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    # load data and visualization，加载数据并可视化\n",
    "    data = loadData('data.xls')                     # 通过调用 loadData 函数，导入原始数据集 文件 'data.xls'，并赋值给 data\n",
    "    X = data[:,:2]                                  # 将数据集 data 的 第一列 和 第二列 的所有行的数据，赋值给　Ｘ, 实际对应的是 身高（m）、　月薪（元）的原始数据  \n",
    "    y = data[:,2]                                   # 将数据集 data 的 第三列 所有行的数据，赋值给　y，实际对应的是 是否有兴趣尝试交往（Y=1/N=0）的原始数据，可取 0 或 1  \n",
    "    \n",
    "    # plot data\n",
    "    plt_data = plt.figure(1)\n",
    "    p1, p2 = plotData(X, y)                    # 通过调用 plotData 函数，输入参数为 数据集 X 和 y， 绘制图像\n",
    "\n",
    "    #Labels and Legend\n",
    "    plt.xlabel('tall')                              # 通过调用 plt.xlabel 函数，设置图像的横坐标名称为'tall'，意思是： 身高（m）\n",
    "    plt.ylabel('salary')                            # 通过调用 plt.ylabel 函数，设置图像的纵坐标名称为'salary'，意思是： 月薪（元）\n",
    "    # 通过调用 plt.legend 函数，设置图像的图例分别为 'I like you' 和 \"I don't like you\"\n",
    "    # 设置 为线条图图例条目创建的标记点数 numpoints 为 1，图例句柄的长度 handlelength 为0，即：只用散点图形表示图例，没有图例句柄的长度的横线\n",
    "    plt.legend((p1, p2), ('I like you', \"I don't like you\"), numpoints=1, handlelength=0)\n",
    "\n",
    "    # show and save visualized image\n",
    "    plt_data.savefig('visualization_org.png')     # 通过调用 plt.savefig 函数，保存图像，并且图像的文件名为：'visualization_org.jpg'，其中，图片的格式为 'jpg'\n",
    "    plt.show(plt_data)                            # 通过调用 plt.show 函数，显示图像\n",
    "    plt.close(plt_data)                           # 通过调用 plt.close 来关闭窗口\n",
    "\n",
    "    # normalization and visualization：通过调用 normalization 函数，对原始数据集 X 进行归一化\n",
    "    X_norm = normalization(X)\n",
    "    # plot data\n",
    "    plt_norm = plt.figure(1)\n",
    "    # 通过调用 plotData 函数，进行绘图，输入参数是 归一化后的 X_norm 和标签数据 y，返回的是 plt_norm, p1_norm 和 p2_norm\n",
    "    p1_norm, p2_norm = plotData(X_norm, y)\n",
    "\n",
    "    # Labels and Legend\n",
    "    plt.xlabel('tall')                         # 通过调用 plt.xlabel 函数，设置图像的横坐标名称为'tall'，意思是： 身高（m）\n",
    "    plt.ylabel('salary')                       # 通过调用 plt.ylabel 函数，设置图像的纵坐标名称为'salary'，意思是： 月薪（元）\n",
    "    # 通过调用 plt.legend 函数，设置图像的图例分别为 'I like you' 和 \"I don't like you\"\n",
    "    # 设置 为线条图图例条目创建的标记点数 numpoints 为 1，图例句柄的长度 handlelength 为0，即：只用散点图形表示图例，没有图例句柄的长度的横线    \n",
    "    plt.legend((p1_norm, p2_norm), ('I like you', \"I don't like you\"), numpoints=1, handlelength=0)\n",
    "    \n",
    "    # show and save visualized image\n",
    "    # 通过调用 plt.show 函数，显示图像\n",
    "       #请补全 \n",
    "    # 通过调用 plt.savefig 函数，保存图像，并且图像的文件名为：'visualization_norm.jpg'，其中，图片的格式为 'jpg'\n",
    "       #请补全 \n",
    "    # 通过调用 plt.close 函数，关闭窗口\n",
    "       #请补全 \n",
    "    \n",
    "    # optimizing by BSD\n",
    "    iter_num=200                                    # 进行初始化迭代的次数 iter_num，赋值 200 给 iter_num\n",
    "    lr=0.05                                        # 进行初始化学习率 lr，赋值 0.001 给 lr\n",
    "    m,n = np.shape(data)                            # 通过使用 np.shape 函数，得到数据集 data 的形状大小，其中，m 为数据集 data 的行数，n 为数据集 data 的列数\n",
    "    offset = np.ones((m, 1))                        # 通过使用 np.ones 函数，创建元素全为 1 的矩阵，矩阵的大小为 m 行 1 列，并赋值给 offset, 即：进行 offset  的初始化，令其全为 1\n",
    "    trainMat = np.c_[offset, X_norm]                # 通过使用 np.c_ 函数将 offset 和 归一化后的 X_norm 数据集组合起来，并赋值给 trainMat\n",
    "    theta=BGD(trainMat,y,iter_num,lr)               # 通过调用 BGD 函数，即：批量梯度下降法（Batch Gradient Descent，BGD），返回最优化后的权重， 并赋值给 theta\n",
    "\n",
    "    ## Plot Boundary\n",
    "    # 通过调用 plotDecisionBoundary 函数，绘制分类决策的直线，其中，输入参数分别是：训练集 trainMat, 标签 y, 最优化后的权重 theta 和 迭代次数 iter_num\n",
    "    plotDecisionBoundary(trainMat, y, theta, iter_num)\n",
    "    cost = loss(trainMat, y, theta)                 # 通过调用 loss 函数，计算出本模型算法的损失函数，其中, 输入参数分别是： 训练集 trainMat, 标签 y 和 最优化后的权重 theta， 并赋值给 cost   \n",
    "    print('Cost theta: {0}'.format(cost))           # 在屏幕上输出 损失函数的数值，其中，.format(cost) 的格式是更加规范的输出格式，当然也可以用转义字符 %s\n",
    "\n",
    "    # Compute accuracy on our training set\n",
    "    p = Precision(trainMat, y, theta)               # 通过调用 Precision 函数，计算出预测 测试集结果的正确率，其中，输入参数分别是： 训练集 trainMat, 标签 y 和 最优化后的权重 theta， 并赋值给 p\n",
    "    print('Train Accuracy: {0}'.format(p))          # 在屏幕上输出 测试集正确率的数值，其中，.format(p) 的格式是更加规范的输出格式，当然也可以用转义字符 %s    \n",
    "    print('finished!')                              # 在屏幕上输出完成的信息，'finished!' \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
